package httpclient

import (
	"crypto/tls"
	"net/http"
	"net/url"
)

// Client HTTP 客户端
type Client struct {
	config     *Config
	httpClient *http.Client
	chain      *Chain
}

// New 创建新的 HTTP 客户端
func New(config *Config) *Client {
	if config == nil {
		config = DefaultConfig()
	}

	// 创建传输层配置
	transport := &http.Transport{
		MaxIdleConns:        config.MaxIdleConns,
		MaxIdleConnsPerHost: config.MaxIdleConnsPerHost,
		IdleConnTimeout:     config.IdleConnTimeout,
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: config.InsecureSkipVerify,
		},
	}

	// 配置代理
	if config.ProxyURL != "" {
		if proxyURL, err := url.Parse(config.ProxyURL); err == nil {
			transport.Proxy = http.ProxyURL(proxyURL)
		}
	}

	// 创建 HTTP 客户端
	client := &http.Client{
		Transport: transport,
		Timeout:   config.Timeout,
		Jar:       config.Jar,
	}

	// 创建拦截器链
	chain := NewChain(
		&AuthInterceptor{
			Username: config.Username,
			Password: config.Password,
			Token:    config.Token,
		},
		&RetryInterceptor{
			MaxRetries: config.MaxRetries,
			RetryDelay: config.RetryDelay,
		},
	)

	return &Client{
		config:     config,
		httpClient: client,
		chain:      chain,
	}
}

// Do 执行 HTTP 请求
func (c *Client) Do(req *Request) (*Response, error) {
	httpReq, err := req.Build()
	if err != nil {
		return nil, err
	}

	// 添加默认请求头
	for key, value := range c.config.Headers {
		if httpReq.Header.Get(key) == "" {
			httpReq.Header.Set(key, value)
		}
	}

	// 执行请求
	var httpResp *http.Response
	var respErr error

	httpResp, respErr = c.chain.Execute(httpReq, func(r *http.Request) (*http.Response, error) {
		return c.httpClient.Do(r)
	})

	if respErr != nil {
		return nil, respErr
	}

	return &Response{
		Response: httpResp,
	}, nil
}

// Get 发送 GET 请求
func (c *Client) Get(url string) *Request {
	return NewRequest(http.MethodGet, url)
}

// Post 发送 POST 请求
func (c *Client) Post(url string) *Request {
	return NewRequest(http.MethodPost, url)
}

// Put 发送 PUT 请求
func (c *Client) Put(url string) *Request {
	return NewRequest(http.MethodPut, url)
}

// Delete 发送 DELETE 请求
func (c *Client) Delete(url string) *Request {
	return NewRequest(http.MethodDelete, url)
}

// Patch 发送 PATCH 请求
func (c *Client) Patch(url string) *Request {
	return NewRequest(http.MethodPatch, url)
}

// Head 发送 HEAD 请求
func (c *Client) Head(url string) *Request {
	return NewRequest(http.MethodHead, url)
}

// Options 发送 OPTIONS 请求
func (c *Client) Options(url string) *Request {
	return NewRequest(http.MethodOptions, url)
}
